package com.zpark.se.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 线程实现方式三：实现Callable接口
 * Callable接口是Runable接口的增强版。同样用call()方法作为线程的执行体，增强了之前的run()方法。
 * 因为call方法可以有返回值，也可以声明抛出异常。
 *         Future接口用来代表Callable接口里的call()方法的返回值，FutureTask类是Future接
 * 口的一个实现类，FutureTask类实现了RunnableFuture接口，而RunnableFuture接口继承了
 * Runnable和Future接口，所以说FutureTask是一个提供异步计算的结果的任务。
 *         步骤如下：
 *                 1.创建一个类MyCallable实现Callable接口
 *                 2.重写call (是有返回值的，表示多线程运行的结果)
 *                 3.创建MyCallable的对象(表示多线程要执行的任务)
 *                 4.创建FutureTask的对象(作用管理多线程运行的结果)
 *                 5.创建Thread类的对象，并启动(表示线程)
 */
public class Demo04 implements Callable<String> {
    @Override
    public String call() throws Exception {
        // 循环10万次
        for (int i = 0; i < 100000; i++) {
            System.out.println("线程Demo04执行了" + (i+1) + "次");
        }
        return "任务执行完成";
    }

    public static void main(String[] args) throws Exception {
        // 创建Demo04的对象
        Demo04 d4 = new Demo04();
        // 创建FutureTask的对象(作用管理多线程运行的结果)
        FutureTask<String> task = new FutureTask<String>(d4);
        // 创建Thread类的对象，并启动(表示线程)
        Thread t = new Thread(task);

        // 启动线程
        t.start();

        // 获取线程返回值
        /*
         * get()方法会阻塞当前线程，直到获取到返回值，才会向下执行。
         */
        String s = task.get();
        System.out.println(s);
        // 循环10万次
        for (int i = 0; i < 100; i++) {
            System.out.println("线程main执行了" + (i+1) + "次");
        }
    }
}
